home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / DJGPP / GAS211S2.ZIP / src / gas-211 / opcodes / z8k-dis.c < prev    next >
C/C++ Source or Header  |  1993-05-30  |  14KB  |  570 lines

  1. /*
  2. This file is part of GNU Binutils.
  3.  
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. GNU General Public License for more details.
  13.  
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software
  16. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  17.  
  18. #include <ansidecl.h>
  19. #include "sysdep.h"
  20. #include "dis-asm.h"
  21.  
  22. #define DEFINE_TABLE
  23. #include "z8k-opc.h"
  24.  
  25.  
  26. #include <setjmp.h>
  27.  
  28.  
  29. typedef struct
  30. {
  31.   /* These are all indexed by nibble number (i.e only every other entry
  32.      of bytes is used, and every 4th entry of words).  */
  33.   unsigned char nibbles[24];
  34.   unsigned char bytes[24];
  35.   unsigned short words[24];
  36.  
  37.   /* Nibble number of first word not yet fetched.  */
  38.   int max_fetched;
  39.   bfd_vma insn_start;
  40.   jmp_buf bailout;
  41.  
  42.   long tabl_index;
  43.   char instr_asmsrc[80];
  44.   unsigned long arg_reg[0x0f];
  45.   unsigned long immediate;
  46.   unsigned long displacement;
  47.   unsigned long address;
  48.   unsigned long cond_code;
  49.   unsigned long ctrl_code;
  50.   unsigned long flags;
  51.   unsigned long interrupts;
  52. }
  53. instr_data_s;
  54.  
  55. /* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
  56.    to ADDR (exclusive) are valid.  Returns 1 for success, longjmps
  57.    on error.  */
  58. #define FETCH_DATA(info, nibble) \
  59.   ((nibble) <= ((instr_data_s *)(info->private_data))->max_fetched \
  60.    ? 1 : fetch_data ((info), (nibble)))
  61.  
  62. static int
  63. fetch_data (info, nibble)
  64.      struct disassemble_info *info;
  65.      int nibble;
  66. {
  67.   char mybuf[20];
  68.   int status;
  69.   instr_data_s *priv = (instr_data_s *)info->private_data;
  70.   bfd_vma start = priv->insn_start + priv->max_fetched / 2;
  71.  
  72.   if ((nibble % 4) != 0)
  73.     abort ();
  74.   status = (*info->read_memory_func) (start,
  75.                       (bfd_byte *) mybuf,
  76.                       (nibble - priv->max_fetched) / 2,
  77.                       info);
  78.   if (status != 0)
  79.     {
  80.       (*info->memory_error_func) (status, start, info);
  81.       longjmp (priv->bailout, 1);
  82.     }
  83.  
  84.   {
  85.     int i;
  86.     char *p = mybuf + priv->max_fetched / 2;
  87.     
  88.     for (i = priv->max_fetched; i < nibble;)
  89.       {
  90.     priv->words[i] = (p[0] << 8) | p[1];
  91.     
  92.     priv->bytes[i] = *p;
  93.     priv->nibbles[i++] = *p >> 4;
  94.     priv->nibbles[i++] = *p &0xf;
  95.  
  96.     ++p;
  97.     priv->bytes[i] = *p;
  98.     priv->nibbles[i++] = *p >> 4;
  99.     priv->nibbles[i++] = *p & 0xf;
  100.  
  101.     ++p;
  102.       }
  103.   }
  104.   priv->max_fetched = nibble;
  105.   return 1;
  106. }
  107.  
  108. static char *codes[16] =
  109. {
  110.   "f",
  111.   "lt",
  112.   "le",
  113.   "ule",
  114.   "ov/pe",
  115.   "mi",
  116.   "eq",
  117.   "c/ult",
  118.   "t",
  119.   "ge",
  120.   "gt",
  121.   "ugt",
  122.   "nov/po",
  123.   "pl",
  124.   "ne",
  125.   "nc/uge"
  126. };
  127.  
  128. int z8k_lookup_instr PARAMS ((unsigned char*, disassemble_info *));
  129. static void output_instr
  130.   PARAMS ((instr_data_s *, unsigned long, disassemble_info *));
  131. static void unpack_instr PARAMS ((instr_data_s *, int, disassemble_info *));
  132. static void unparse_instr PARAMS ((instr_data_s *));
  133.  
  134. static int
  135. print_insn_z8k (addr, info, is_segmented)
  136.      unsigned long addr;
  137.      disassemble_info *info;
  138.      int is_segmented;
  139. {
  140.   instr_data_s instr_data;
  141.  
  142.   info->private_data = (PTR) &instr_data;
  143.   instr_data.max_fetched = 0;
  144.   instr_data.insn_start = addr;
  145.   if (setjmp (instr_data.bailout) != 0)
  146.     /* Error return.  */
  147.     return -1;
  148.  
  149.   instr_data.tabl_index = z8k_lookup_instr (instr_data.nibbles, info);
  150.   if (instr_data.tabl_index > 0)
  151.     {
  152.       unpack_instr (&instr_data, is_segmented, info);
  153.       unparse_instr (&instr_data);
  154.       output_instr (&instr_data, addr, info);
  155.       return z8k_table[instr_data.tabl_index].length;
  156.     }
  157.   else
  158.     {
  159.       FETCH_DATA (info, 4);
  160.       (*info->fprintf_func) (info->stream, ".word %02x%02x",
  161.                  instr_data.bytes[0], instr_data.bytes[2]);
  162.       return 2;
  163.     }
  164. }
  165.  
  166. print_insn_z8001 (addr, info)
  167.      unsigned long addr;
  168.      disassemble_info *info;
  169. {
  170.   return print_insn_z8k (addr, info, 1);
  171. }
  172.  
  173. print_insn_z8002 (addr, info)
  174.      unsigned long addr;
  175.      disassemble_info *info;
  176. {
  177.   return print_insn_z8k (addr, info, 0);
  178. }
  179.  
  180. int
  181. z8k_lookup_instr (nibbles, info)
  182.      unsigned char *nibbles;
  183.      disassemble_info *info;
  184. {
  185.  
  186.   int nibl_index, tabl_index;
  187.   int nibl_matched;
  188.   unsigned short instr_nibl;
  189.   unsigned short tabl_datum, datum_class, datum_value;
  190.  
  191.   nibl_matched = 0;
  192.   tabl_index = 0;
  193.   while (!nibl_matched && z8k_table[tabl_index].name)
  194.     {
  195.       nibl_matched = 1;
  196.       for (nibl_index = 0; nibl_index < z8k_table[tabl_index].length * 2 && nibl_matched; nibl_index++)
  197.     {
  198.       if ((nibl_index % 4) == 0)
  199.         /* Fetch one word at a time.  */
  200.         FETCH_DATA (info, nibl_index + 4);
  201.       instr_nibl = nibbles[nibl_index];
  202.  
  203.       tabl_datum = z8k_table[tabl_index].byte_info[nibl_index];
  204.       datum_class = tabl_datum & CLASS_MASK;
  205.       datum_value = ~CLASS_MASK & tabl_datum;
  206.  
  207.       switch (datum_class)
  208.         {
  209.         case CLASS_BIT:
  210.           if (datum_value != instr_nibl)
  211.         nibl_matched = 0;
  212.           break;
  213.         case CLASS_00II:
  214.           if (!((~instr_nibl) & 0x4))
  215.         nibl_matched = 0;
  216.           break;
  217.         case CLASS_01II:
  218.           if (!(instr_nibl & 0x4))
  219.         nibl_matched = 0;
  220.           break;
  221.         case CLASS_0CCC:
  222.           if (!((~instr_nibl) & 0x8))
  223.         nibl_matched = 0;
  224.           break;
  225.         case CLASS_1CCC:
  226.           if (!(instr_nibl & 0x8))
  227.         nibl_matched = 0;
  228.           break;
  229.         case CLASS_0DISP7:
  230.           if (!((~instr_nibl) & 0x8))
  231.         nibl_matched = 0;
  232.           nibl_index += 1;
  233.           break;
  234.         case CLASS_1DISP7:
  235.           if (!(instr_nibl & 0x8))
  236.         nibl_matched = 0;
  237.           nibl_index += 1;
  238.           break;
  239.         case CLASS_REGN0:
  240.           if (instr_nibl == 0)
  241.         nibl_matched = 0;
  242.           break;
  243.         case CLASS_BIT_1OR2:
  244.           if ((instr_nibl | 0x2) != (datum_value | 0x2))
  245.         nibl_matched = 0;
  246.           break;
  247.         default:
  248.           break;
  249.         }
  250.     }
  251.       if (nibl_matched)
  252.     {
  253.       return tabl_index;
  254.     }
  255.  
  256.       tabl_index++;
  257.     }
  258.   return -1;
  259.  
  260. }
  261.  
  262. static void
  263. output_instr (instr_data, addr, info)
  264.      instr_data_s *instr_data;
  265.      unsigned long addr;
  266.      disassemble_info *info;
  267. {
  268.   int loop, loop_limit;
  269.   char tmp_str[20];
  270.   char out_str[100];
  271.  
  272.   strcpy (out_str, "\t");
  273.  
  274.   loop_limit = z8k_table[instr_data->tabl_index].length * 2;
  275.   FETCH_DATA (info, loop_limit);
  276.   for (loop = 0; loop < loop_limit; loop++)
  277.     {
  278.       sprintf (tmp_str, "%x", instr_data->nibbles[loop]);
  279.       strcat (out_str, tmp_str);
  280.     }
  281.  
  282.   while (loop++ < 8)
  283.     {
  284.       strcat (out_str, " ");
  285.     }
  286.  
  287.   strcat (out_str, instr_data->instr_asmsrc);
  288.  
  289.   (*info->fprintf_func) (info->stream, "%s", out_str);
  290. }
  291.  
  292. static void
  293. unpack_instr (instr_data, is_segmented, info)
  294.      instr_data_s *instr_data;
  295.      int is_segmented;
  296.      disassemble_info *info;
  297. {
  298.   int nibl_count, loop;
  299.   unsigned short instr_nibl, instr_byte, instr_word;
  300.   long instr_long;
  301.   unsigned short tabl_datum, datum_class, datum_value;
  302.  
  303.   nibl_count = 0;
  304.   loop = 0;
  305.   while (z8k_table[instr_data->tabl_index].byte_info[loop] != 0)
  306.     {
  307.       FETCH_DATA (info, nibl_count + 4 - (nibl_count % 4));
  308.       instr_nibl = instr_data->nibbles[nibl_count];
  309.       instr_byte = instr_data->bytes[nibl_count];
  310.       instr_word = instr_data->words[nibl_count];
  311.  
  312.       tabl_datum = z8k_table[instr_data->tabl_index].byte_info[loop];
  313.       datum_class = tabl_datum & CLASS_MASK;
  314.       datum_value = tabl_datum & ~CLASS_MASK;
  315.  
  316.       switch (datum_class)
  317.     {
  318.     case CLASS_X:
  319.       instr_data->address = instr_nibl;
  320.       break;
  321.     case CLASS_BA:
  322.       instr_data->displacement = instr_nibl;
  323.       break;
  324.     case CLASS_BX:
  325.       instr_data->arg_reg[datum_value] = instr_nibl;
  326.       break;
  327.     case CLASS_DISP:
  328.       switch (datum_value)
  329.         {
  330.         case ARG_DISP16:
  331.           instr_data->displacement = instr_word;
  332.           nibl_count += 3;
  333.           break;
  334.         case ARG_DISP12:
  335.           instr_data->displacement = instr_word & 0x0fff;
  336.           nibl_count += 2;
  337.           break;
  338.         default:
  339.           break;
  340.         }
  341.       break;
  342.     case CLASS_IMM:
  343.       switch (datum_value)
  344.         {
  345.         case ARG_IMM4:
  346.           instr_data->immediate = instr_nibl;
  347.           break;
  348.         case ARG_NIM8:
  349.           instr_data->immediate = (-instr_byte);
  350.           nibl_count += 1;
  351.           break;
  352.         case ARG_IMM8:
  353.           instr_data->immediate = instr_byte;
  354.           nibl_count += 1;
  355.           break;
  356.         case ARG_IMM16:
  357.           instr_data->immediate = instr_word;
  358.           nibl_count += 3;
  359.           break;
  360.         case ARG_IMM32:
  361.           FETCH_DATA (info, nibl_count + 8);
  362.           instr_long = (instr_data->words[nibl_count] << 16)
  363.         | (instr_data->words[nibl_count + 4]);
  364.           instr_data->immediate = instr_long;
  365.           nibl_count += 7;
  366.           break;
  367.         case ARG_IMMN:
  368.           instr_data->immediate = instr_nibl - 1;
  369.           break;
  370.           /* ????? */
  371.           /* missing ARG_IMMNMINUS1 */
  372.         case ARG_IMM_1:
  373.           instr_data->immediate = 1;
  374.           break;
  375.         case ARG_IMM_2:
  376.           instr_data->immediate = 2;
  377.           break;
  378.         case ARG_IMM2:
  379.           instr_data->immediate = instr_nibl & 0x3;
  380.           break;
  381.         default:
  382.           break;
  383.         }
  384.       break;
  385.     case CLASS_CC:
  386.       instr_data->cond_code = instr_nibl;
  387.       break;
  388.     case CLASS_CTRL:
  389.       instr_data->ctrl_code = instr_nibl;
  390.       break;
  391.     case CLASS_DA:
  392.     case CLASS_ADDRESS:
  393.       if (is_segmented)
  394.         {
  395.           if (instr_nibl & 0x8)
  396.         {
  397.           FETCH_DATA (info, nibl_count + 8);
  398.           instr_long = (instr_data->words[nibl_count] << 16)
  399.             | (instr_data->words[nibl_count + 4]);
  400.           instr_data->address = ((instr_word & 0x7f00) << 8) +
  401.             (instr_long & 0xffff);
  402.           nibl_count += 7;
  403.         }
  404.           else
  405.         {
  406.           instr_data->address = ((instr_word & 0x7f00) << 8) +
  407.             (instr_word & 0x00ff);
  408.           nibl_count += 3;
  409.         }
  410.         }
  411.       else
  412.         {
  413.           instr_data->address = instr_word;
  414.           nibl_count += 3;
  415.         }
  416.       break;
  417.     case CLASS_0CCC:
  418.       instr_data->cond_code = instr_nibl & 0x7;
  419.       break;
  420.     case CLASS_1CCC:
  421.       instr_data->cond_code = instr_nibl & 0x7;
  422.       break;
  423.     case CLASS_0DISP7:
  424.       instr_data->displacement = instr_byte & 0x7f;
  425.       nibl_count += 1;
  426.       break;
  427.     case CLASS_1DISP7:
  428.       instr_data->displacement = instr_byte & 0x7f;
  429.       nibl_count += 1;
  430.       break;
  431.     case CLASS_01II:
  432.       instr_data->interrupts = instr_nibl & 0x3;
  433.       break;
  434.     case CLASS_00II:
  435.       instr_data->interrupts = instr_nibl & 0x3;
  436.       break;
  437.     case CLASS_BIT:
  438.       /* do nothing */
  439.       break;
  440.     case CLASS_IR:
  441.       instr_data->arg_reg[datum_value] = instr_nibl;
  442.       break;
  443.     case CLASS_FLAGS:
  444.       instr_data->flags = instr_nibl;
  445.       break;
  446.     case CLASS_REG:
  447.       instr_data->arg_reg[datum_value] = instr_nibl;
  448.       break;
  449.     case CLASS_REG_BYTE:
  450.       instr_data->arg_reg[datum_value] = instr_nibl;
  451.       break;
  452.     case CLASS_REG_WORD:
  453.       instr_data->arg_reg[datum_value] = instr_nibl;
  454.       break;
  455.     case CLASS_REG_QUAD:
  456.       instr_data->arg_reg[datum_value] = instr_nibl;
  457.       break;
  458.     case CLASS_REG_LONG:
  459.       instr_data->arg_reg[datum_value] = instr_nibl;
  460.       break;
  461.     case CLASS_REGN0:
  462.       instr_data->arg_reg[datum_value] = instr_nibl;
  463.       break;
  464.     default:
  465.       break;
  466.     }
  467.  
  468.       loop += 1;
  469.       nibl_count += 1;
  470.     }
  471. }
  472.  
  473. static void
  474. unparse_instr (instr_data)
  475.      instr_data_s *instr_data;
  476. {
  477.   unsigned short tabl_datum, datum_class, datum_value;
  478.   int loop, loop_limit;
  479.   char out_str[80], tmp_str[25];
  480.  
  481.   sprintf (out_str, "\t%s\t", z8k_table[instr_data->tabl_index].name);
  482.  
  483.   loop_limit = z8k_table[instr_data->tabl_index].noperands;
  484.   for (loop = 0; loop < loop_limit; loop++)
  485.     {
  486.       if (loop)
  487.     strcat (out_str, ",");
  488.  
  489.       tabl_datum = z8k_table[instr_data->tabl_index].arg_info[loop];
  490.       datum_class = tabl_datum & CLASS_MASK;
  491.       datum_value = tabl_datum & ~CLASS_MASK;
  492.  
  493.       switch (datum_class)
  494.     {
  495.     case CLASS_X:
  496.       sprintf (tmp_str, "0x%0x(R%d)", instr_data->address,
  497.            instr_data->arg_reg[datum_value]);
  498.       strcat (out_str, tmp_str);
  499.       break;
  500.     case CLASS_BA:
  501.       sprintf (tmp_str, "r%d(#%x)", instr_data->arg_reg[datum_value],
  502.            instr_data->immediate);
  503.       strcat (out_str, tmp_str);
  504.       break;
  505.     case CLASS_BX:
  506.       sprintf (tmp_str, "r%d(R%d)", instr_data->arg_reg[datum_value],
  507.            instr_data->arg_reg[ARG_RX]);
  508.       strcat (out_str, tmp_str);
  509.       break;
  510.     case CLASS_DISP:
  511.       sprintf (tmp_str, "#0x%0x", instr_data->displacement);
  512.       strcat (out_str, tmp_str);
  513.       break;
  514.     case CLASS_IMM:
  515.       sprintf (tmp_str, "#0x%0x", instr_data->immediate);
  516.       strcat (out_str, tmp_str);
  517.       break;
  518.     case CLASS_CC:
  519.       sprintf (tmp_str, "%s", codes[instr_data->cond_code]);
  520.       strcat (out_str, tmp_str);
  521.       break;
  522.     case CLASS_CTRL:
  523.       sprintf (tmp_str, "0x%0x", instr_data->ctrl_code);
  524.       strcat (out_str, tmp_str);
  525.       break;
  526.     case CLASS_DA:
  527.     case CLASS_ADDRESS:
  528.       sprintf (tmp_str, "#0x%0x", instr_data->address);
  529.       strcat (out_str, tmp_str);
  530.       break;
  531.     case CLASS_IR:
  532.       sprintf (tmp_str, "@R%d", instr_data->arg_reg[datum_value]);
  533.       strcat (out_str, tmp_str);
  534.       break;
  535.     case CLASS_FLAGS:
  536.       sprintf (tmp_str, "0x%0x", instr_data->flags);
  537.       strcat (out_str, tmp_str);
  538.       break;
  539.     case CLASS_REG_BYTE:
  540.       if (instr_data->arg_reg[datum_value] >= 0x8)
  541.         {
  542.           sprintf (tmp_str, "rl%d",
  543.                instr_data->arg_reg[datum_value] - 0x8);
  544.         }
  545.       else
  546.         {
  547.           sprintf (tmp_str, "rh%d", instr_data->arg_reg[datum_value]);
  548.         }
  549.       strcat (out_str, tmp_str);
  550.       break;
  551.     case CLASS_REG_WORD:
  552.       sprintf (tmp_str, "r%d", instr_data->arg_reg[datum_value]);
  553.       strcat (out_str, tmp_str);
  554.       break;
  555.     case CLASS_REG_QUAD:
  556.       sprintf (tmp_str, "rq%d", instr_data->arg_reg[datum_value]);
  557.       strcat (out_str, tmp_str);
  558.       break;
  559.     case CLASS_REG_LONG:
  560.       sprintf (tmp_str, "rr%d", instr_data->arg_reg[datum_value]);
  561.       strcat (out_str, tmp_str);
  562.       break;
  563.     default:
  564.       break;
  565.     }
  566.     }
  567.  
  568.   strcpy (instr_data->instr_asmsrc, out_str);
  569. }
  570.